import axios from "axios";
import jwt_decode from "jwt-decode";

const hour23 = 1000 * 60 * 60 * 23;

/**
 * 修改使用的认证信息
 * @param {*} token 传入 token / null
 */
const useToken = (token) => {
  if (token) axios.defaults.headers.common["Authorization"] = "Bearer " + token;
  else axios.defaults.headers.common["Authorization"] = null;
};

export default {
  state: {
    id: null,
    userinfo: {},
    is_login: false,
    is_staff: false,
    access: null,
    access_time: null,
  },
  getters: {},
  mutations: {
    UpdateUserInfo(state, info) {
      state.id = info.id;
      state.userinfo = info;
      state.is_staff = info.is_staff;
    },
    updateToken(state, info) {
      state.is_login = true;
      state.access = info.access;
      state.access_time = info.access_time;
      useToken(info.access);
    },
    logout(state) {
      state.id = null;
      state.is_login = false;
      state.is_staff = false;
      state.access = state.access_time = null;
      state.userinfo = {};
      localStorage.removeItem("refresh");
      localStorage.removeItem("access");
      localStorage.removeItem("access_time");
      useToken(null);
    },
  },
  actions: {
    login(context, data) {
      return new Promise((resolve, reject) => {
        axios
          .post("/api/api/token/", {
            username: data.username,
            password: data.password,
          })
          .then((response) => {
            const expired_time = Date.parse(response.headers.date) + hour23;
            context.commit("updateToken", {
              ...response.data,
              access_time: expired_time,
            });
            // 获取信息
            context.dispatch("getUserInfo", {
              id: jwt_decode(response.data.refresh).user_id,
            });
            // 放入储存
            localStorage.setItem("refresh", response.data.refresh);
            localStorage.setItem("access", response.data.access);
            localStorage.setItem("access_time", expired_time);
            resolve(response.data);
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
    /**
     *
     * @param {*} context
     * @returns 正确获得access
     */
    checkStatus(context) {
      return new Promise((resolve, reject) => {
        // 是否登录
        if (!context.state.is_login) {
          const refresh = localStorage.getItem("refresh");
          if (!refresh) {
            // 没有登录信息
            reject("没有登录信息");
            return;
          }
          context.commit("updateToken", {
            access: localStorage.getItem("access"),
            access_time: localStorage.getItem("access_time"),
          });
          /**
           * 获得基本信息
           */
          context.dispatch("getBadges");
          context.dispatch("getCollections");
          // 获取用户信息
          context.dispatch("getUserInfo", {
            id: jwt_decode(refresh).user_id,
          });
        }

        // 正常登录，检验下认证时间
        let expiredTime = context.state.access_time;
        if (expiredTime > new Date().getTime()) {
          // 有效账户
          resolve(context.state.access);
          return;
        }

        // access令牌过期 ，尝试通过refresh 更新
        axios
          .post("/api/api/token/refresh/", {
            refresh: localStorage.getItem("refresh"),
          })
          .then((response) => {
            // 更新成功
            expiredTime = Date.parse(response.headers.date) + hour23;
            context.commit("updateToken", {
              access_time: expiredTime,
              access: response.data.access,
            });
            // 更新储存
            localStorage.setItem("access", response.data.access);
            localStorage.setItem("access_time", expiredTime);
            resolve(response.data.access);
          })
          .catch((error) => {
            // 更新失败
            context.commit("logout");
            reject(error);
            return;
          });
      });
    },
    getUserInfo(context, data) {
      return new Promise((resolve, reject) => {
        axios
          .get(`/api/users/${data.id}/`)
          .then((response) => {
            context.commit("UpdateUserInfo", {
              ...response.data,
              id: response.data.id,
              is_staff: response.data.is_staff,
            });
            resolve(response);
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
  },
  modules: {},
};
